package com.wnn.demo.model.system.service;


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wnn.demo.advice.MyException;
import com.wnn.demo.domain.Permission;
import com.wnn.demo.domain.Role;
import com.wnn.demo.domain.RoleAndPerm;
import com.wnn.demo.model.system.mapper.PermissionMapper;
import com.wnn.demo.model.system.mapper.RoleMapper;
import com.wnn.demo.pojo.ResultCode;
import com.wnn.demo.shiro.MyRealm;
import com.wnn.demo.utils.IdWorker;
import com.wnn.demo.utils.MyStringUtil;
import com.wnn.demo.vo.MenuTreeVo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author WN
 */
@Service
public class RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private IdWorker idWorker;


    @Autowired
    private UserService userService;

    public Role findRoleById(String id){
        return roleMapper.selectByPrimaryKey(id);
    }

    public int addRole(Map< String, Object > map) {

        String name = (String) map.get("name");
        String description = (String) map.get("description");
        if (StringUtils.isEmpty(name)){
            throw  new MyException(ResultCode.NULL);
        }
        String id = idWorker.nextId() + "";
        Role role = new Role(id,name,description);
        return roleMapper.insert(role);
    }

    public PageInfo< Role > findAll(Integer page, Integer limit) {
        PageHelper.startPage(page,limit);
        List< Role > roles = roleMapper.selectAll();
        return new PageInfo<>(roles);
    }

    public int deleteRoleById(String id) {
        Role role = findRoleById(id);
        if (role==null){
            throw new MyException(ResultCode.NULLPARM);
        }
        return roleMapper.delete(role);
    }

    public int saveRole(String id, Map< String, Object > map) {
        Role role = findRoleById(id);
        String name = (String) map.get("name");
        if (StringUtils.isEmpty(name)){
            throw new MyException(ResultCode.NULLPARM);
        }
        String description = (String) map.get("description");
        role.setName(name);
        role.setDescription(description);
        return roleMapper.updateByPrimaryKey(role);

    }

    public List< MenuTreeVo > findRoleHavePerm(String roleId) {
        //查找所有权限菜单
        List< MenuTreeVo > allPermTreeList = permissionMapper.selectAllPermTreeVo();
        //查找角色拥有的所有权限
        List<MenuTreeVo> rolePermAllList = roleMapper.findRoleHavePerm(roleId);
        for (MenuTreeVo perm:allPermTreeList
             ) {
            String permissionId = perm.getPermissionId();
            for (MenuTreeVo rolePerm:rolePermAllList
                 ) {
                if (permissionId.equals(rolePerm.getPermissionId())){
                    perm.setChecked(1);
                }
            }
        }
        //找到权限的一级菜单
        List< MenuTreeVo > parentParentList = allPermTreeList.stream()
                .filter(p -> "0".equals(p.getParentId()) || MyStringUtil.isNullOrEmpty(p.getParentId()))
                .collect(Collectors.toList());
        for (MenuTreeVo p:parentParentList
             ) {
            String permissionId = p.getPermissionId();
            ArrayList< MenuTreeVo > childMenuTreeList = new ArrayList<>();
            for (MenuTreeVo allPerm:allPermTreeList
                 ) {
                if (permissionId.equals(allPerm.getParentId())){
                    childMenuTreeList.add(allPerm);
                }
            }
            p.setChildren(userService.selectIndexChildMenu(permissionId,allPermTreeList));
        }
        return  parentParentList;
    }


    /**
     * 分配角色拥有的权限
     * @param roleId
     * @param permissionList
     * @return
     */
    public int assignRolePerm(String roleId,List< Permission > permissionList) {
        //存储前端更改的ids列表
        ArrayList< String >  ids = new ArrayList<>();
        //存储数据库role_perm已有的permId
        ArrayList<String> dataIds = new ArrayList<>();
        //根据角色ID查找出角色拥有的中间表信息 role_perm
        List< RoleAndPerm > roleAndPermDataList = roleMapper.findRoleAndPermList(roleId, null);
        //把前端传递的Permission列表转成 id存入 ids列表中做对比准备
        for (Permission p:permissionList
             ) {
            ids.add(p.getPermissionId());
        }
        for (RoleAndPerm p:roleAndPermDataList
        ) {
            dataIds.add(p.getPermId());
        }
        //创建对比的新增列表和删除列表
        ArrayList< String > deleteIds = new ArrayList<>();
        ArrayList<  String > insertIds = new ArrayList<>();
        // 对比获得删除ids
        for (String id: dataIds
             ) {
            // contains 包含方法 如果 id在列表ids中包含返回true
            if (!ids.contains(id)){
                deleteIds.add(id);
            }
        }
        //对比获取增加ids
        for (String id: ids
             ) {
            if (!dataIds.contains(id)){
                insertIds.add(id);
            }
        }
//      批量增加
        List<Map> mapInsertList = new ArrayList<>();
        for (String id: insertIds
             ) {
            Map<String,String> map = new HashMap<>(16);
            map.put("id",idWorker.nextId() + "");
            map.put("permId",id);
            mapInsertList.add(map);
        }
        if (mapInsertList.size()>0){
            int i = roleMapper.batchInsertRoleAndPerm(roleId,mapInsertList);
        }
        if (deleteIds.size()>0){
            int t = roleMapper.batchDeleteRoleAndPerm(roleId,deleteIds);
        }
//       角色、权限更新后 需要清除所有用户的授权缓存
        DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
        MyRealm shiroRealm = (MyRealm) securityManager.getRealms().iterator().next();
        shiroRealm.clearAllCachedAuthorizationInfo();
        return 1;
    }



    /**
     * 批量删除角色
     * @param ids
     * @return
     */
    public int batchDeleteRoleByIds(String ids) {



        List< Role > roles = roleMapper.selectRoleByIds(ids);

        if (roles.isEmpty()){
            throw new MyException(ResultCode.NULLPARM);
        }

        return  roleMapper.batchDeleteRoleByList(roles);

    }
}
